package com.chushouya.order.service.common.impl;

import com.chushouya.common.shunfeng.dto.SfCreateOrderDTO;
import com.chushouya.common.support.Contexts;
import com.chushouya.order.constants.*;
import com.chushouya.order.rabbitmq.sender.AlipayFlowMessageSender;
import com.chushouya.order.service.async.OrderAlipayAsyncFactory;
import com.chushouya.order.service.async.OrderAsyncManager;
import com.general.framework.core.enums.ContextUserType;
import com.general.framework.core.exception.Ex;
import com.chushouya.manager.config.BizConfigEnum;
import com.chushouya.manager.dto.admin.clerk.ClerkInfoDTO;
import com.chushouya.manager.service.api.ClerkApiService;
import com.chushouya.manager.service.common.ConfigApiService;
//=====order.constants.*;
import com.chushouya.order.constants.*;
import com.chushouya.order.dao.entity.OrderEntity;
import com.chushouya.order.dao.repository.OrderRepository;
import com.chushouya.order.rabbitmq.sender.ExpressReservationMessageSender;
import com.chushouya.order.rabbitmq.sender.NotifyMessageSender;
import com.chushouya.order.service.admin.OrderLogisticsService;
import com.chushouya.order.service.common.CommonOrderActionService;
import com.chushouya.order.service.common.OrderExpressService;
import com.chushouya.order.service.common.OrderLogService;
import com.general.framework.core.lang.Dates;
import com.general.framework.core.lang.Integers;
import com.general.framework.core.lang.Jsons;
import com.general.framework.core.lang.Strings;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

@Service
@Slf4j
public class CommonOrderActionServiceImpl implements CommonOrderActionService {

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private OrderLogService orderLogService;

    @Resource
    private ClerkApiService clerkApiService;

    @Resource
    private ConfigApiService configApiService;

    @Resource
    private NotifyMessageSender notifyMessageSender;

    @Resource
    private OrderExpressService orderExpressService;

    @Resource
    private OrderLogisticsService OrderLogisticsService;

    @Resource
    private ExpressReservationMessageSender expressReservationMessageSender;

    @Resource
    private AlipayFlowMessageSender alipayFlowMessageSender;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void waitOrder(OrderEntity orderEntity, String remark) {
        final Long orderId = orderEntity.getOrderId();
        remark = Strings.defaultString(remark);
        orderLogService.addOrderActionLog(orderId, OrderActionEnum.CALL_ORDER.value(), remark);
    }

    @Override
    public void returnAgain(OrderEntity orderEntity, String remark, Integer value) {
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(value);
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.RETURN_AGAIN.value(), remark);
    }

    @Override
    public void returnPay(OrderEntity orderEntity, String remark, Integer value) {
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(value);
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.RETURN_PAY.value(), remark);

    }

    @Override
    public void sendEnergy(OrderEntity orderEntity, String remark) {
        //插入备注
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.FOLLOW_ORDER.value(), remark);

    }

    @Override
    public void resetOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        final Long orderId = orderEntity.getOrderId();
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderId);
        update.setUpdateTime(new Date());
        update.setOrderStatus(orderStatus);
        update.setPrepaidPrice(BigDecimal.ZERO);
        orderRepository.updateByPrimaryKeySelective(update);
        String msg = Strings.format("重置订单状态为：{}", OrderStatusEnum.WAIT_CHECK.named());
        //插入修改备注
        orderLogService.addOrderActionLog(orderId, OrderActionEnum.UPDATE_ORDER.value(), msg);
    }

    @Override
    public void qualityOrder(OrderEntity orderEntity, String remark, Integer value,BigDecimal qualityPrice) {
        final Long orderId = orderEntity.getOrderId();
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(value);
        update.setQualityPrice(qualityPrice);
        update.setQualityTime(Dates.getTimeNow());
        update.setCompletePrice(qualityPrice);
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.QUALITY_ORDER.value(), remark);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {

        final Long orderId = orderEntity.getOrderId();
        final Long partnerId = orderEntity.getPartnerId();
        //操作用户类型
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderId);
        Integer userType = Contexts.getUserContext().getUserType();
        if (ContextUserType.APP_USER.value().equals(userType)) {
            update.setCancelTime(Dates.getTimeNow());
        } else {
            update.setCloseTime(Dates.getTimeNow());
        }
        update.setLogisticsStatus(LogisticsStatusEnum.NONE.value());
        update.setOrderStatus(orderStatus);
        orderRepository.updateByPrimaryKeySelective(update);

        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.CLOSE_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderId, PartnerNotifyTypeEnum.CANCEL.value(), remark);
        expressReservationMessageSender.sendExpressCancelMessage(orderEntity);
        notifyMessageSender.sendAlipaySubscribeMessage(orderId, orderEntity.getPlatform(), "RECYCLE_CANCEL");
        OrderAsyncManager.me().executeDelay2s(OrderAlipayAsyncFactory.alipayCloseOrder(orderId));
    }

    /**
     * 签收
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void receiveOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        final Long orderId = orderEntity.getOrderId();
        final Long partnerId = orderEntity.getPartnerId();
        OrderEntity update = new OrderEntity();
        //更新订单状态
        update.setOrderId(orderEntity.getOrderId());
        update.setReceiveTime(Dates.getTimeNow());
        update.setLogisticsStatus(LogisticsStatusEnum.HAS_RECEIPT.value());
        update.setOrderStatus(orderStatus);
        update.setOrderType(OrderTypeEnum.EXPRESS_RECYCLE.value());
        update.setClerkName("");
        update.setClerkId(0L);
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.RECEIVE_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderId, PartnerNotifyTypeEnum.RECEIVE.value(), remark);
//        alipayFlowMessageSender.sendAlipayFlowMessage(orderEntity);
        OrderAsyncManager.me().executeDelay2s(OrderAlipayAsyncFactory.alipayOrderReceive(orderId));

    }

    /**
     * 派单
     *
     * @param orderEntity
     * @param clerkId
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void dispatchOrder(OrderEntity orderEntity, Long clerkId, String remark, Integer orderStatus) {
        final Long orderId = orderEntity.getOrderId();
        ClerkInfoDTO clerkInfoDTO = clerkApiService.getClerkInfo(clerkId);
        if (Objects.isNull(clerkInfoDTO)){
            throw Ex.business("业务员不存在");
        }
        log.info("派单给业务员：{},电话:{}", clerkInfoDTO.getClerkName(), clerkInfoDTO);
        //修改订单
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setClerkId(clerkId);
        update.setClerkName(clerkInfoDTO.getClerkName());
        update.setOrderStatus(orderStatus);
        update.setOrderType(OrderTypeEnum.DOOR_RECYCLE.value());
        String msg = Strings.format("派单给{}业务员：{},电话:{} {}", clerkInfoDTO.getCity(), clerkInfoDTO.getClerkName(), clerkInfoDTO.getClerkPhone(), remark);
        update.setDispatchTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.DISPATCH_ORDER.value(), msg);

        // 通过队列异步发送通知消息
        notifyMessageSender.sendSmsNotifyMessage(orderId);
        notifyMessageSender.sendWechatNotifyMessage(orderId);
        notifyMessageSender.sendOrderStatusNotifyMessage(orderId);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderId, PartnerNotifyTypeEnum.DISPATCH.value(), msg);
//        OrderAsyncManager.me().executeDelay2s(OrderAlipayAsyncFactory.alipayOrderDelivery(orderId, AlipayFinishAllDeliveryEnum.GENERATED_LOGISTICS_ORDER.value()));

    }

    /**
     * 议价
     *
     * @param orderEntity
     * @param completePrice
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bargainOrder(OrderEntity orderEntity, BigDecimal completePrice, String remark, Integer orderStatus) {

        final Long orderId = orderEntity.getOrderId();
        final Long partnerId = orderEntity.getPartnerId();
        BigDecimal completePriceRange = BigDecimal.ZERO;
        try {
            final String completePriceRangeValue = configApiService.getStringConfig(BizConfigEnum.COMPLETE_PRICE_RANGE.getConfigKey());
            completePriceRange = new BigDecimal(completePriceRangeValue);
        } catch (IllegalArgumentException e) {
            throw Ex.business("订单议价区间设置错误");
        }

        //成交价不能大于订单总价+成交价区间
        if (completePrice.compareTo(orderEntity.getOrderPrice().add(completePriceRange)) > 0) {
            throw Ex.business("成交价不能大于订单价的{}元以上", completePriceRange);
        }
        //修改订单
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setCompletePrice(completePrice);
        update.setOrderStatus(orderStatus);
        update.setBargainTime(Dates.getTimeNow());
        update.setLogisticsStatus(LogisticsStatusEnum.HAS_RECEIPT.value());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.COMPLETE_BARGAIN.value(), remark);
        alipayFlowMessageSender.sendAlipayFlowMessage(orderEntity);
    }

    /**
     * 重新议价
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void reBargainOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        //修改状态
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        update.setBargainTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.REBARGAIN_ORDER.value(), remark);

    }

    /**
     * 完成订单
     *
     * @param orderEntity
     * @param payType
     * @param completePrice
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeOrder(OrderEntity orderEntity, Integer payType, BigDecimal completePrice, String remark, Integer orderStatus) {

        final Long orderId = orderEntity.getOrderId();
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        //修改付款状态
        if (!Integers.isNullOrZero(payType)) {
            update.setPayStatus(OrderPayStatusEnum.BALANCE.value());
            update.setPayType(payType);
        }

        update.setOrderStatus(OrderStatusEnum.COMPLETE.value());
        update.setCompletePrice(completePrice);
        if (Objects.equals(orderEntity.getOrderType(), OrderTypeEnum.DOOR_RECYCLE.value())) {
            update.setLogisticsStatus(LogisticsStatusEnum.WAIT_DELIVERY.value());
        }
        update.setCompleteTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.COMPLETE_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderEntity.getOrderId(), PartnerNotifyTypeEnum.COMPLETE.value(), remark);

        notifyMessageSender.sendAlipaySubscribeMessage(orderId, orderEntity.getPlatform(), "PAYMENT_RECEIVED");
    }

    /**
     * 业务员确认订单
     *
     * @param orderEntity
     * @param appointStartTime
     * @param appointEndTime
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void confirmOrder(OrderEntity orderEntity, Date appointStartTime, Date appointEndTime, String remark, Integer orderStatus) {
        final Long orderId = orderEntity.getOrderId();
        final Long partnerId = orderEntity.getPartnerId();
        //修改状态
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderId);
        update.setOrderStatus(orderStatus);
        update.setAppointStartTime(appointStartTime);
        update.setAppointEndTime(appointEndTime);
        update.setConfirmTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);
        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.CONFIRM_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderEntity.getOrderId(), PartnerNotifyTypeEnum.CONFIRM.value(), remark);

    }

    /**
     * 业务员接单
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void acceptOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        //修改状态
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        update.setAcceptTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.ACCEPT_ORDER.value(), remark);
    }

    /**
     * 业务员上门
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void visitOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        final Long partnerId = orderEntity.getPartnerId();
        final Long orderId = orderEntity.getOrderId();
        //修改状态
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        update.setVisitTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.VISIT_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderId, PartnerNotifyTypeEnum.VISIT.value(), remark);
    }

    /**
     * 申请撤单
     *
     * @param orderEntity
     * @param backoutRemark
     * @param orderStatus
     */

    @Override
    public void requestBackout(OrderEntity orderEntity, String backoutRemark, Integer orderStatus) {
        //修改订单
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.BACKOUT_ORDER.value(), backoutRemark);

    }

    /**
     * 撤单审核不通过
     *
     * @param orderEntity
     * @param backoutRemark
     * @param orderStatus
     */

    @Override
    public void requestBackoutReject(OrderEntity orderEntity, String backoutRemark, Integer orderStatus) {
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.BACKOUT_ORDER.value(), Strings.format("撤单审核不通过:{}", backoutRemark));
    }

    /**
     * 撤单成功
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    public void backoutOrderSuccess(OrderEntity orderEntity, String remark, Integer orderStatus) {
        //修改订单
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(OrderStatusEnum.BACKOUT_CLOSED.value());
        orderRepository.updateByPrimaryKeySelective(update);

        //插入订单操作记录
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.CLOSE_ORDER.value(), remark);


    }

    /**
     * 确认发货
     *
     * @param orderEntity
     * @param remark
     * @param orderStatus
     */

    @Override
    public void deliveryOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {
        final Long partnerId = orderEntity.getPartnerId();
        final Long orderId = orderEntity.getOrderId();
        OrderEntity update = new OrderEntity();
        update.setOrderId(orderEntity.getOrderId());
        update.setOrderStatus(orderStatus);
        update.setDeliveryTime(Dates.getTimeNow());
        update.setLogisticsStatus(LogisticsStatusEnum.HAS_DELIVERY.value());
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderEntity.getOrderId(), OrderActionEnum.DELIVERY_ORDER.value(), remark);
        notifyMessageSender.sendPartnerOrderStatusNotifyMessage(orderId, PartnerNotifyTypeEnum.DELIVERY.value(), remark);
        OrderAsyncManager.me().executeDelay2s(OrderAlipayAsyncFactory.alipayOrderDelivery(orderId, AlipayFinishAllDeliveryEnum.COURIER_HAS_PICKED_UP.value()));

    }

    @Override
    public void returnOrder(OrderEntity orderEntity, String remark, Integer orderStatus) {

        final Long orderId = orderEntity.getOrderId();
        //插入订单退货记录
        SfCreateOrderDTO sfCreateOrderDTO = orderExpressService.reserveReturn(orderEntity);
        if (Objects.isNull(sfCreateOrderDTO) || Objects.isNull(sfCreateOrderDTO.getExpressNo())) {
            orderLogService.addOrderActionLog(orderId, OrderActionEnum.DELIVERY_ORDER.value(), remark);
            throw Ex.business("预约退货失败");
        }
        final String expressNo = sfCreateOrderDTO.getExpressNo();

        final String msg = Strings.format("{} 预约退货成功 {}",remark, expressNo);
        OrderLogisticsService.saveOrderLogistics(sfCreateOrderDTO, orderId, LogisticsTypeEnum.USER_RETURN.value());
        closeOrder(orderEntity, msg, orderStatus);


    }

    /**
     * 预约快递
     */

    @Override
    public void deliverOrder(OrderEntity orderEntity, String actionNote, Integer value) {
        final Long orderId = orderEntity.getOrderId();
        final Long partnerId = orderEntity.getPartnerId();
        //预约快递
        SfCreateOrderDTO sfCreateOrderDTO = orderExpressService.reserve(orderEntity);
        if (Objects.isNull(sfCreateOrderDTO) || Objects.isNull(sfCreateOrderDTO.getExpressNo())) {
            orderLogService.addOrderActionLog(orderId, OrderActionEnum.DELIVERY_ORDER.value(), sfCreateOrderDTO.getErrorMsg());
            throw Ex.business("预约快递失败 {}", Jsons.toJsonString(sfCreateOrderDTO));
        }
        final String expressNo = sfCreateOrderDTO.getExpressNo();

        final String msg = Strings.format("{} 预约快递成功 {}",actionNote, expressNo);

        OrderEntity update = new OrderEntity();
        update.setOrderId(orderId);
        update.setOrderStatus(OrderStatusEnum.WAIT_PICKUP.value());
        update.setDeliveryTime(Dates.getTimeNow());
        orderRepository.updateByPrimaryKeySelective(update);
        orderLogService.addOrderActionLog(orderId, OrderActionEnum.RESERVE_ORDER.value(), msg);
        OrderLogisticsService.saveOrderLogistics(sfCreateOrderDTO, orderId, LogisticsTypeEnum.USER_SEND.value());
        OrderAsyncManager.me().executeDelay2s(OrderAlipayAsyncFactory.alipayOrderDelivery(orderId, AlipayFinishAllDeliveryEnum.GENERATED_LOGISTICS_ORDER.value()));

    }



}
